//import com.kanq.common.utils.HanlpUtils;
//import com.kanq.common.utils.SseUtil;
//import com.kanq.pojo.entity.KanqAiFile;
//import com.kanq.pojo.entity.KanqAiFileChunk;
//import com.kanq.pojo.request.ChatRequest;
//import com.kanq.pojo.response.ChatResponse;
//import com.kanq.pojo.response.RefFile;
//import io.qdrant.client.grpc.Points;
//import org.springframework.web.bind.annotation.PostMapping;
//import org.springframework.web.bind.annotation.RequestBody;
//import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
//import reactor.core.Disposable;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.concurrent.Executors; /**
// * 处理直接聊天请求
// * 该方法接收一个聊天请求，然后通过SSE（Server-Sent Events）方式发送聊天响应
// * 它会根据请求的问题，搜索相关的文档片段，并使用预设的模板和LLM（Large Language Model）服务进行回答
// *
// * @param request 聊天请求对象，包含用户的问题
// * @return 返回一个SseEmitter对象，用于服务器向客户端发送事件
// */
//@PostMapping("/chat")
//public SseEmitter chatDirect(@RequestBody ChatRequest request) {
//    // 检查是否存在直接聊天的模板，如果不存在则从数据库中获取
//    if (chatDirectlyTemplate == null) {
//        chatDirectlyTemplate = kanqAiPromptService.getByName("chat_directly");
//    }
//
//    // 创建一个SseEmitter对象，设置超时时间为3分钟
//    SseEmitter emitter = new SseEmitter(3 * 60 * 1000L);
//    // 在单独的线程中执行聊天逻辑，以避免阻塞主线程
//    Executors.newSingleThreadExecutor().submit(() -> {
//        ChatResponse response = new ChatResponse();
//        List<Points.ScoredPoint> result2;
//        List<KanqAiFile> fileWithChunks;
//
//        try {
//            // 设置聊天响应的阶段信息，并发送到客户端
//            response.setStage("文档检索中...");
//            SseUtil.sseSend(emitter, response);
//            // 对问题进行分词，获取关键字
//            List<String> keywords = HanlpUtils.hanLPSegment(request.getQuestion());
//            // 根据关键字在知识库中全文搜索，获取相关文件块ID
//            List<Long> chunkIds = kanqAiFileChunkService.fullTextSearch(keywords).stream().map(KanqAiFileChunk::getId).toList();
//            //判断chunkIds 是否为空 为空返回
//            if (chunkIds.isEmpty()) {
//                // 根据用户的问题，搜索相关的文档片段
//                result2 = qdrantService.searchVector(qdrantService.getEmbedding(request.getQuestion()), topK);
//                for (var x : result2) {
//                    log.info("score {}", x.getScore());
//                }
//
//                List<Long> chunkIds2 = result2.stream().map(x -> x.getId().getNum()).toList();
//                fileWithChunks = kanqAiFileService.getFileWithChunksV2(chunkIds2);
//            } else {
//                result2 = qdrantService.searchVector(qdrantService.getEmbedding(request.getQuestion()), topK, chunkIds);
//                List<Long> chunkIds2 = result2.stream().map(x -> x.getId().getNum()).toList();
//                // 根据文件块ID获取文件及其内容片段
//                fileWithChunks = kanqAiFileService.getFileWithChunksV2(chunkIds2);
//            }
//            // 更新聊天响应的阶段信息，并发送到客户端
//            response.setStage("检索完成，问题回答中...");
//            SseUtil.sseSend(emitter, response);
//            StringBuffer sb = new StringBuffer();
//            // 使用模板和搜索到的文档片段，以及用户的问题，生成聊天回答的内容
//            List<KanqAiFileChunk> r = extractChunks(fileWithChunks);
//            String t = chatDirectlyTemplate.replace("{context}", rerankChunks(request.getQuestion(), r)).replace("{question}", request.getQuestion());
//
//            log.info("t===> \n" + t);
//
//            // 订阅LLM服务的流式回答，处理响应
//            response.setStage("message");
//            Disposable disposable = llmService
//                    .streamChat(t).doOnComplete(() -> {
//                        response.setDone(true);
//                        response.setStage("end");
//                        response.setContent("");
//                        List<RefFile> refs = new ArrayList<>();
//                        for (var f : fileWithChunks) {
//                            refs.add(new RefFile(f.getName(), f.getId()));
//                        }
//                        response.setRefs(refs);
//                        SseUtil.sseSend(emitter, response);
//                        log.info("complete===> \n" + sb);
//
//                        // 异步生成并保存标题和问题还有答案
//                        Executors.newSingleThreadExecutor().submit(() -> {
//                            String title = kanqAiHistoryService.generateTitle(request.getQuestion());
//                            Long titleId = kanqAiHistoryService.saveTitle(title);
//                            Long questionId = kanqAiHistoryQuestionService.saveQuestion(request.getQuestion(), titleId);
//                            kanqAiHistoryAnswerService.saveAnswer(questionId, sb.toString());
//                        });
//                    })
//                    .subscribe(value -> {
//                                sb.append(value);
//                                response.setContent(value);
//                                SseUtil.sseSend(emitter, response);
//                            }, emitter::completeWithError,
//                            emitter::complete);
//
//            // 错误处理，如果发生异常且订阅未取消，则取消订阅
//            emitter.onError((e) -> {
//                if (!disposable.isDisposed()) {
//                    disposable.dispose();
//                }
//            });
//        } catch (Exception e) {
//            log.error("error===> \n" + e.getMessage());
//            // 异常处理，如果在处理请求过程中发生异常，发送异常信息到客户端，并完成SSE连接
//            response.setStage("end");
//            response.setContent("查询相关条目异常。");
//            SseUtil.sseSend(emitter, response);
//            emitter.complete();
//        }
//    });
//
//    // 返回SseEmitter对象，用于服务器向客户端发送事件
//    return emitter;
//}
